/**
 * 每个节点没有up只有子节点
 */
var Node = {
	//类变量和方法
	createNew: function(id, 名称) {
		let self = { id: id, name: 名称, up: null, children: [] }
		return self;
	},
	/**
	 * json必须是对象而不是数组  children 必须是数组
	 * 结构表 第一个是id字段名, 第二项是name字段名 第三项是children字段名, 第四项开始是 其他属性
	 */
	json2Object: function(json, 结构表, up) {
		if (json == null) return null;
		let 结构 = 结构表 || ["id", "name", "children"];
		let obj = {};
		obj.id = json[结构[0]];
		obj.name = json[结构[1]];
		obj.up = up;
		obj.children = [];
		for (let index = 3; index < 结构.length; index++) {
			const key = 结构[index];
			if (json.hasOwnProperty(key))
				obj[key] = json[key];
		}
		if (json.hasOwnProperty(结构[2])) {
			let children = json[结构[2]];
			if (children)
				for (let i = 0; i < children.length; ++i) {
					let c = this.json2Object(children[i], 结构, obj);
					if (c) obj.children.push(c);
				}
		}
		return obj;
	},
	/**
	* obj必须是对象而不是数组  children 必须是数组
	* 结构表 第一个是id字段名, 第二项是name字段名 第三项是children字段名, 第四项开始是 其他属性
	*/
	object2Json: function(obj, 结构表) {
		if (obj == null) return null;
		// let 类型=Object.prototype.toString.call(obj);
		// if (类型!="[object Object]") return null;
		let 结构 = 结构表 || ["id", "name", "children"];
		let json = {};
		json[结构[0]] = obj.id;
		json[结构[1]] = obj.name;
		json[结构[2]] = [];
		for (let index = 3; index < 结构.length; index++) {
			const key = 结构[index];
			if (obj.hasOwnProperty(key))
				json[key] = obj[key];
		}
		if (obj.hasOwnProperty(结构[2])) {
			let children = obj[结构[2]];
			if (children)
				for (let i = 0; i < children.length; ++i) {
					let c = this.object2Json(children[i], 结构);
					if (c) json[结构[2]].push(c);
				}
		}
		return json;
	},
	/**
	   * json必须是数组  children 必须是数组
	   * 结构表 第一个是id字段名, 第二项是name字段名 第三项是children字段名, 第四项开始是 其他属性
	   */
	json2Array: function(json, 结构表, up) {
		if (json == null) return null;
		let 结构 = 结构表 || ["id", "name", "children"];
		let arr = [];
		for (let i = 0; i < json.length; ++i) {
			let obj2 = json[i];
			let obj = {};
			obj.id = obj2[结构[0]];
			obj.name = obj2[结构[1]];
			obj.up = up;
			for (let index = 3; index < 结构.length; index++) {
				const key = 结构[index];
				if (obj2.hasOwnProperty(key))
					obj[key] = obj2[key];
			}
			if (obj2.hasOwnProperty(结构[2]) && obj2[结构[2]]) {
				obj.children = this.json2Array(obj2[结构[2]], 结构, obj);
			}
			arr.push(obj)
		}
		return arr;
	},

	/**
	 * json必须是数组  children 必须是数组
	 * 结构表 第一个是id字段名, 第二项是name字段名 第三项是children字段名, 第四项开始是 其他属性
	 */
	array2Json: function(arr, 结构表) {
		if (arr == null) return null;
		let 结构 = 结构表 || ["id", "name", "children"];
		let json = []
		for (let i = 0; i < arr.length; ++i) {
			let obj2 = arr[i];
			let obj = {};
			obj[结构[0]] = obj2.id;
			obj[结构[1]] = obj2.name;
			for (let index = 3; index < 结构.length; index++) {
				const key = 结构[index];
				if (obj2.hasOwnProperty(key))
					obj[key] = obj2[key];
			}
			if (obj2.hasOwnProperty(结构[2]) && obj2[结构[2]]) {
				obj[结构[2]] = this.array2Json(obj2[结构[2]], 结构);
			}
			json.push(obj);
		}
		return json;
	},

	add子节点: function(节点, 子节点) {
		if (节点 && 子节点) {
			节点.children.push(子节点);
			子节点.up = 节点
		}
	},
	chg子节点: function(节点, 第n个子节点, 子节点) {
		if (节点.children.length > 第n个子节点) {
			节点.children[个子节点] = 子节点
			子节点.up = 节点
		}
	},
	del子节点: function(节点, 第n个子节点) {
		if (节点.children.length > 第n个子节点) {
			节点.children.splice(第n个子节点, 1)
		}
	},
	search: function(节点, 节点id) {
		return this.down直到(节点, function(nd) {
			if (nd.id == 节点id)
				return nd;
			else
				return null;
		})
	},
	downArr: function(数组, call) {
		if (数组 && call)
			for (let i = 0; i < 数组.length; ++i) {
				let 子节点 = 数组[i];
				// console.log("子节点", key, 子节点)
				this.downall(子节点, call);
			}
	},
	downArr直到: function(数组, call) {
		if (数组 && call)
			for (let i = 0; i < 数组.length; ++i) {
				let 子节点 = 数组[i];
				// console.log("子节点", key, 子节点)
				this.downall(子节点, call);
			}
	},
	downall: function(节点, call) {
		if (节点 == null || call == null) return;
		call(节点);
		if (节点.hasOwnProperty("children")) {
			for (let i = 0; i < 节点.children.length; ++i) {
				let 子节点 = 节点.children[i];
				// console.log("子节点", key, 子节点)
				this.downall(子节点, call);
			}
		}
	},
	down直到: function(节点, call) {
		if (节点 == null || call == null) return null;
		let flag = call(节点);
		if (flag != null) {          //如果为true 停止遍历
			return 节点;
		}//如果为false 继续遍历
		if (节点.hasOwnProperty("children")) {
			for (let i = 0; i < 节点.children.length; ++i) {
				children
				let 子节点 = 节点.children[i];
				let obj = this.down直到(子节点, call);
				if (obj != null) return obj;
			}
		}
		return null;
	},
	upall: function(节点, call) {
		if (节点 == null || call == null) return;
		call(节点)
		this.upall(节点.up, call)
	},
	up直到: function(节点, call) {
		if (节点 == null || call == null) return null;
		// console.log(节点)
		let obj = call(节点)
		if (obj != null)
			return obj;
		return this.up直到(节点.up, call);
	}

}


// let nd = Node.createNew('1',  1 );
// let nd1 = Node.createNew('2',  2 );
// let nd2 = Node.createNew('3',  3 );
// let nd21 = Node.createNew('4',  4 );
// let nd3 = Node.createNew('5',  5 );
// let nd31 = Node.createNew('6',  6 );
// let nd32 = Node.createNew('7',  7 );
// let nd311 = Node.createNew('8',  8 );
// let nd3111 = Node.createNew('9',  9 );

// Node.add子节点(nd, nd1)
// Node.add子节点(nd, nd2)
// Node.add子节点(nd2, nd21)
// Node.add子节点(nd, nd3)
// Node.add子节点(nd3, nd31)
// Node.add子节点(nd3, nd32)
// Node.add子节点(nd31, nd311)
// Node.add子节点(nd311, nd3111)
// Node.downall(nd, function (ndd) {
//     console.log(ndd)
// })
// let ndd = Node.search(nd, '8');
// console.log(ndd)

// let ndd = Node.up直到(nd311, function (nddd) {
//     if (nddd.id == '5') {
//         console.log(nddd)
//         return nddd
//     }    else
//         return null;
// })


// Node.upall(nd3111, function (nddd) {
//     console.log(nddd.id)
// })
export default Node;